#lang racket
(define-syntax when
  (syntax-rules ()
    ((_ pred b1 ...)
     (if pred 
         (begin b1 ...)
         '()))))

(define-syntax while
  (syntax-rules ()
    ((_ pred b1 ...)
     (let loop []
       (when pred b1 ... (loop))))))

(define-syntax for
  (syntax-rules ()
    ((_ (i from to) b1 ...)
     (let loop [(i from)]
       (when (< i to)
         b1 ...
         (loop (+ 1 i)))))
    ((_ (i from to step) b1 ...)
        (let loop [(i from)]
          (when (< i to)
            b1 ...
            (loop (+ i step)))))))

(for (i 0 10 2)
  (display i)
  (display #\Space))

(define-syntax incf
  (syntax-rules ()
    ((_ x) (begin (set! x (+ x 1)) x))
    ((_ x i) (begin (set! x (+ x i)) x))))

;(let ((i 0))
;    (display (incf i))
;    (incf j 4))

(define-syntax my-and
  (syntax-rules ()
    ((_) #t)
    ((_ e) e)
    ((_ e1 e2 ...)
     (if e1
         (my-and e2 ...)
         #f))))

(define-syntax my-or
  (syntax-rules ()
    ((_) #f)
    ((_ e) e)
    ((_ e1 e2 ...)
     (let ((t e1))
       (if t t (my-or e2 ...))))))

(define-syntax my-let*
    (syntax-rules ()
      ((_ ((x y) (m n)) z)
       (begin (define x y)
              (define m n)
              z))))
(my-let* ((x 3) (y x)) ((lambda (x y) (+ x y)) x y))
; => 3

(define-syntax my-cond
  (syntax-rules (else)
    ((_ (else e1 ...))
     (begin e1 ...))
    ((_ (e1 e2 ...))
     (when e1 e2 ...))
    ((_ (e1 e2 ...) c1 ...)
     (if e1
         (begin e2 ...)
         (cond c1 ...)))))
(my-cond ((> 3 4) 'cao)
         ((= 3 3) 'fuck))

(define-syntax unless
  (syntax-rules ()
    ((_ pred b1 ...)
     (if (not pred)
         (begin
           b1 ...)
         'helloworld))))

(define-syntax my-let*
  (syntax-rules ()
    ((_ ((p v)) b ...)
     (let ((p v)) b ...))
    ((_ ((p1 v1) (p2 v2) ...) b ...)
     (let ((p1 v1))
       (my-let* ((p2 v2) ...)
		b ...)))))
		
(define-syntax set-cdr!
  (syntax-rules ()
    ((_ l1 l2)
     (define l1 (cons (car l1) l2)))))

(define-syntax set-car!
  (syntax-rules ()
    ((_ l1 l2)
     (define l1 (cons l2 (cdr l1))))))
